package com.soywer.rpc.rpc10;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;

/**
 * 功能描述：
 *
 * @author 18065916_李猛
 * @since 2021/3/8
 */
public class Server {
    private static boolean running = true;
    public static void main(String[] args) throws Exception {

        //创建一个Socket服务端
        ServerSocket ss = new ServerSocket(8888);
        while (running) {
            Socket s = ss.accept();
            process(s);
            s.close();
        }
        ss.close();
    }

    private static void process(Socket s) throws Exception{
        InputStream in = s.getInputStream();
        OutputStream out = s.getOutputStream();
        //对象输入流-读取参数--使用hessian
        Hessian2Input ois = new Hessian2Input(in);
        //对象输出流-写对象--使用hessian
        Hessian2Output oos = new Hessian2Output(out);

        //类名
        String clazzName = ois.readString();
        //方法名
        String methodName = ois.readString();
        //方法参数类型
        Class[] parameterTypes = (Class[])HessianUtil.deserialize(ois.readBytes());
        //方法参数
        Object[] args = (Object[])HessianUtil.deserialize(ois.readBytes());
        System.out.println("客户端要调用的类名称：" + clazzName);
        System.out.println("客户端要调用的方法名称：" + methodName);
        System.out.print("客户端要调用的方法参数类型：");
        for (Class parameterType : parameterTypes) {
            System.out.print(parameterType + "\t");
        }
        System.out.println();
        System.out.print("客户端要调用的方法参数：" + args);
        for (Object arg : args) {
            System.out.print(arg + "\t");
        }
        System.out.println();

        //实例化对象
        Class clazz = null;

        //1，可以从服务注册表找到具体的类，比如spring的bean管理
        //2，或者手动配置接口的实现类
        //例如：客户端传递过来的是：com.soywer.rpc.common.IUserService
        //那么需要配置这个接口的实现，
        //比如配置文件写到：com.soywer.rpc.common.IUserService=com.soywer.rpc.rpc06.UserServiceImpl
        //然后使用反射动态加载类Class.forName("com.soywer.rpc.rpc06.UserServiceImpl");
        clazz = ProductServiceImpl.class;
        //获取需要调用的方法
        Method method = clazz.getMethod(methodName,parameterTypes);
        //执行该方法调用-传递实体及参数
        Object o = (Object)method.invoke(clazz.newInstance(),args);

        //二进制输入流-写参数
        oos.writeBytes(HessianUtil.serialize(o));
        //数据输出流刷新
        oos.flush();
    }
}
